class_name Player
extends CharacterBody2D

signal player_die

const SPEED = 150.0
const JUMP_VELOCITY = -400.0
var health := 1
var curr_mode := Mode.SMALL
var gravity_scale := 1.0
var level_pass = false
var player_stop = false
var player_in_upDown = false
var fall_flag = false

var can_fire = true
@export var fire_rate = 0.25  # 发射间隔(秒)

@onready var starts_timer: Timer = $StartsTimer
@export var starts_status := false # 无敌星持续状态

@onready var animated_normal = $AnimatedNormal
@onready var animated_big = $AnimatedBig
@onready var animated_fire = $AnimatedFire
@onready var collision_shape_2d = $CollisionShape2D
@onready var attack_box: Area2D = $AttackBox

var animatedProxy : AnimatedSprite2D
var player_direction = Vector2.RIGHT
var bgm_stop_position : float

const PLAYER_BIG = preload("res://shape/player_big.tres")
const PLAYER_NORMAL = preload("res://shape/player_normal.tres")
const BULLET = preload("res://sence/bullet.tscn")
const FIREBALL = preload("res://asserts/sound/fireball.ogg")
const SMALL_JUMP = preload("res://asserts/sound/small_jump.ogg")
const POWERUP_APPEARS = preload("res://asserts/sound/powerup_appears.ogg")
const MAIN_THEME = preload("res://asserts/music/main_theme.ogg")
const MAIN_THEME_SPED_UP = preload("res://asserts/music/main_theme_sped_up.ogg")
const DEATH = preload("res://asserts/music/death.ogg")

enum Mode{
	SMALL,
	LARGE,
	FIRE
}

func _eat(item:Node2D):
	if item is MushRoom:
		if item.mushroom_type == Brick.SpawnItem.UPGRADE:
			_health_up()
		elif item.mushroom_type == Brick.SpawnItem.LIFE:
			GlobalGameInfo.player_life += 1
		else:
			print_rich("[color=red]暂未定义mushroom_type=%s的处理逻辑[/color]" % item.mushroom_type)
	elif item is Flower:
		_health_up()
	elif item is Star:
		_open_starts_status(13.5)
	else:
		print_rich("[color=red]暂未定义item=%s的处理逻辑[/color]" % item.name)
	
func changePlayerInfo():
	animated_normal.visible = false
	animated_big.visible = false
	animated_fire.visible = false
	
	if health == 1:
		curr_mode = Mode.SMALL
		animatedProxy = animated_normal
		collision_shape_2d.shape = PLAYER_NORMAL 
		collision_shape_2d.position = Vector2(0,0)
		attack_box.get_node("CollisionShape2D").shape = PLAYER_NORMAL
		attack_box.get_node("CollisionShape2D").position = Vector2(0,0)
	elif health == 2: # health == 2
		curr_mode = Mode.LARGE
		animatedProxy = animated_big
		collision_shape_2d.shape = PLAYER_BIG
		collision_shape_2d.position = Vector2(0,-8)
		attack_box.get_node("CollisionShape2D").shape = PLAYER_BIG
		attack_box.get_node("CollisionShape2D").position = Vector2(0,-8)
	else : # health == 3
		curr_mode = Mode.FIRE
		animatedProxy = animated_fire
		collision_shape_2d.shape = PLAYER_BIG
		collision_shape_2d.position = Vector2(0,-8)
		attack_box.get_node("CollisionShape2D").shape = PLAYER_BIG
		attack_box.get_node("CollisionShape2D").position = Vector2(0,-8)
	animatedProxy.visible = true

func _ready():
	changePlayerInfo()
	attack_box.visible = false

func _physics_process(delta):
	if player_in_upDown:
		return
	if player_stop:
		play_animations(0)
		return
	if level_pass:
		velocity.x = SPEED
		if not is_on_floor():
			velocity += get_gravity() * delta * gravity_scale
		play_animations(1)
		move_and_slide()
		return
	# Add the gravity.
	if not is_on_floor():
		velocity += get_gravity() * delta * gravity_scale
	# Handle jump.
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY
		$AudioStreamPlayer.stream = SMALL_JUMP
		$AudioStreamPlayer.play()

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var direction = Input.get_axis("ui_left", "ui_right")
	if direction == 1:
		player_direction = Vector2.RIGHT
		$GunPosition.position = Vector2(16,-16)
		
	elif direction == -1 :
		player_direction = Vector2.LEFT
		$GunPosition.position = Vector2(-16,-16)
		
	if direction:
		velocity.x = direction * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
	# fire
	if health == 3 && Input.is_action_just_pressed("fire") && can_fire:
		shoot()
		can_fire = false
		await get_tree().create_timer(fire_rate).timeout
		can_fire = true
	
	play_animations(direction)
	
	move_and_slide()

func shoot():
	var bullet = BULLET.instantiate()
	bullet.name = "Bullet%d" % (get_child_count() + 1)
	bullet.position = $GunPosition.position
	bullet.direction = player_direction
	add_child(bullet)
	$AudioStreamPlayer.stream = FIREBALL
	$AudioStreamPlayer.play()

func take_hit(hitFrom:Node2D,damage:int):
	if starts_status:
		return 
	health = max(0,health-1)
	print("player 受到来自%s的%s伤害. health剩余%s" % [hitFrom.name, damage,health])
	starts_status = true
	starts_timer.start(2.5)
	if health == 1 || health == 2:
		_health_down()
	else:
		_died()

func play_animations(direction):
	if health == 0 || player_in_upDown:
		return
	if fall_flag:
		animatedProxy.play("slow_down")
		return
	if is_on_floor():
		if direction > 0 :
			animatedProxy.flip_h = false
			animatedProxy.play("run")
		elif direction < 0:
			animatedProxy.flip_h = true
			animatedProxy.play("run")
		else:
			animatedProxy.play("idle")
	else:
		animatedProxy.play("jump")

func _health_down():
	player_in_upDown = true
	collision_shape_2d.set_deferred("disabled",true)
	#collision_shape_2d.disabled = true
	animatedProxy.play("health_down")
	await get_tree().create_timer(1.0).timeout
	# 替换图片
	changePlayerInfo()
	$AudioStreamPlayer.stream = POWERUP_APPEARS
	$AudioStreamPlayer.play()
	# 还原设置
	collision_shape_2d.set_deferred("disabled",false)
	#collision_shape_2d.disabled = false
	player_in_upDown = false

func _health_up():
	health = min(3,health+1)
	player_in_upDown = true
	animatedProxy.play("health_up")
	await get_tree().create_timer(1.0).timeout
	# 替换图片
	changePlayerInfo()
	# 还原设置
	player_in_upDown = false

	# 替换图片
	changePlayerInfo()

func _open_starts_status(waitTime):
	attack_box.visible = true
	starts_status = true
	collision_layer &= ~2
	starts_timer.start(waitTime)
	# 播放动画
	$AnimationPlayer.play("changeColor",-1,2.0,false)
	#bgm_stop_position = %BGM.get_playback_position()
	#%BGM.stop()
	#%BGM.stream = MAIN_THEME_SPED_UP
	#%BGM.play(bgm_stop_position)

func _died():
	print("Player died!")
	$AudioStreamPlayer.stream = DEATH
	$AudioStreamPlayer.play()
	animatedProxy.play("died")
	gravity_scale = 0.25
	self.get_node("CollisionShape2D").queue_free()
	var tween = create_tween()
	var target_position = self.position
	target_position.y -= 64
	tween.tween_property(self,"position",target_position,0.5)
	player_die.emit()

func auto_move():
	print("auto move to door")
	fall_flag = false
	player_stop = false
	level_pass = true
	gravity_scale = 1.0

func _on_flags_player_stop():
	player_stop = true
	velocity = Vector2.ZERO
	gravity_scale = 0

func _on_flags_fall_flag():
	fall_flag = true
	
func _on_starts_timer_timeout() -> void:
	print("player 结束 starts模式")
	bgm_stop_position = %BGM.get_playback_position()
	%BGM.stop()
	%BGM.stream = MAIN_THEME
	%BGM.play(bgm_stop_position)
	$AnimationPlayer.play("RESET")
	starts_status = false
	attack_box.visible = false
	# 添加layer2 
	collision_layer |= 2

func _on_attack_box_body_entered(body: Node2D) -> void:
	if body.has_method("_hit_box"):
		print("%s 给[%s]造成一次伤害" % [name,body.name])
		body._hit_box(self)
